// Copyright (c) 2021 G_night

/*
	协程池定义
*/
package agopool

import (
	"sync"
	"sync/atomic"
)

// A goroutine pool
type AgoPool struct {
	cap            uint64            // 总容量
	runningWorkers uint64            // 运行中任务
	status         PoolStatus        // 池状态
	chTask         chan *Task        // 任务缓存池
	isBlock        bool              // 是否阻塞（默认阻塞）
	panicHandler   func(interface{}) // 错误处理方式
	overTimeFunc   TimeoutFunc       // 非阻塞处理方法
	sync.Mutex                       // 锁
}

// 获取一个协程池
func NewPool() *AgoPool {
	pool := &AgoPool{
		cap:            DefaultAgoPoolSize,
		status:         OPENED,
		runningWorkers: 0,
		isBlock:        DefaultIsBlock,
		chTask:         make(chan *Task, DefaultAgoPoolSize),
	}
	return pool
}

// 设置初始大小
func NewPoolWithCap(cap uint64) *AgoPool {
	pool := NewPool()
	pool.cap = cap
	pool.chTask = make(chan *Task, cap)
	return pool
}

// 初始化增加非阻塞模式
func NewNotBlockPool(cap uint64) *AgoPool {
	pool := NewPoolWithCap(cap)
	pool.isBlock = false
	return pool
}

// runningWorkers + 1
func (p *AgoPool) incWorker() {
	atomic.AddUint64(&p.runningWorkers, 1)
}

// runningWorkers - 1
func (p *AgoPool) decWorker() {
	atomic.AddUint64(&p.runningWorkers, ^uint64(0))
}

// 获取当前 runningWorkers
func (p *AgoPool) GetWorker() uint64 {
	return atomic.LoadUint64(&p.runningWorkers)
}

// 获取容量大小
func (p *AgoPool) GetCap() uint64 {
	return p.cap
}

// 修改状态，若状态未变化则返回false
func (p *AgoPool) setStatus(status PoolStatus) bool {
	p.Lock()
	defer p.Unlock()
	if p.status == status {
		return false
	}
	p.status = status
	return true
}

// 设置错误处理方式
func (p *AgoPool) SetPanicHandler(handler func(interface{})) {
	p.panicHandler = handler
}

// 设置非阻塞的超时方法
func (p *AgoPool) SetTimeoutAfterFunc(afterFunc TimeoutFunc) {
	if !p.isBlock {
		p.overTimeFunc = afterFunc
	}
}
